/*
=======================================================================

Heads Up Display for BotS

=======================================================================
*/


#include "cg_local.h"
#include "cgame_BOTS.h"

#include "BOTS_HUD.h"

#include "../game/bots_game2cgame.h"

#ifdef Q3_VM
// can you say hack?
#include "BOTS_HUD_widgets.c"
#endif


///////////////////////////////////////////////////////
// Static shit
float colors[4][4] = { 
//		{ 0.2, 1.0, 0.2, 1.0 } , { 1.0, 0.2, 0.2, 1.0 }, {0.5, 0.5, 0.5, 1} };
		{ 1, 0.69, 0, 1.0 } ,		// normal
		{ 1.0, 0.2, 0.2, 1.0 },		// low health
		{0.5, 0.5, 0.5, 1},			// weapon firing
		{ 1, 1, 1, 1 } };			// health > 100



// Globals. 
int			
	iCLASSTYPE,	// client's current class (captain, bodyguard, ...)
	iLEVEL;		// client's current promotion level

const char	*info = NULL;	//csfix: kludge


///////////////////////////////////////////////////////
// BOTS_updateClassData
//
// This function will update class data present in the CS_BOTS_CLIENT
// config string
//
void BOTS_updateClassData() {
	const char	*csInfo = CG_ConfigString(CS_BOTS_CLIENT + cg.snap->ps.clientNum);
	

	iCLASSTYPE	= atoi(Info_ValueForKey(csInfo, "c"));
	iLEVEL		= atoi(Info_ValueForKey(csInfo, "lev"));
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Class panels
static float BOTS_HUD_panelCAPTAIN(float y, int iLevel, int iTeam) {
	static stData_t
		stSplitmode, stGrenademode, stKey, stWarcry;
	bots_g2cg_captain_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_captain_t);


	updateData(&stSplitmode,	p->weapons.weaponmode);
	updateData(&stGrenademode,	p->weapons.grenademode);
	updateData(&stKey,			p->sKeyDistance );
	updateData(&stWarcry,		p->sWarcryDelay);

	if (!stSplitmode.iData) {
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stSplitmode,cgs.media.botsHUDiconsOther[generic_normal]);
	}
	else {
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stSplitmode,cgs.media.botsHUDiconsOther[generic_split + stSplitmode.iData]);
	}
	// Grenade mode
	y = BOTS_HUD_drawSwitch(y- BOTS_HUD_PANEL_MARGIN,iTeam,&stGrenademode,cgs.media.botsHUDiconsOther[grenade_proxy]);

	// Warcry
	y = BOTS_HUD_drawTimer(y,iTeam,&stWarcry,cgs.media.botsHUDiconsOther[captain_warcry]);
	// Key...
	y = BOTS_HUD_drawKey(y,iTeam,&stKey,cgs.media.botsHUDiconsOther[generic_key]);
	return y;
}

static float BOTS_HUD_panelBODYGUARD(float y, int iLevel, int iTeam) {
	static stData_t
		stLState, stLTime,stProtect,stProtected,stPulse,stDecoy, stGrenademode;
	bots_g2cg_bodyguard_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_bodyguard_t);


	updateData(&stLState,		(p->bits & (1<<BOTS_G2CG_BODYGUARD_LASERON))?1:0);
	updateData(&stPulse,		(p->bits & (1<<BOTS_G2CG_BODYGUARD_PULSE))?1:0);	
	updateData(&stLTime,		p->sLaserTime);

	updateData(&stDecoy,		p->sDecoyDelay);

	updateData(&stProtect,		(p->bits & (1<<BOTS_G2CG_BODYGUARD_PROTECTING))?1:0);
	updateData(&stProtected,	p->sProtected);


	// Grenade mode
	updateData(&stGrenademode,	p->weapons.grenademode);
	y = BOTS_HUD_drawSwitch(y,iTeam,&stGrenademode,cgs.media.botsHUDiconsOther[grenade_proxy]); //FIX:

	// Decoy
	if (iLevel > 0)
		y = BOTS_HUD_drawTimer(y,iTeam,&stDecoy,cgs.media.botsHUDiconsOther[bodyguard_decoy]);

	// Laser
	y = BOTS_HUD_drawLaser(y,iTeam,&stLState,&stLTime,stPulse.iData); // Cooling/On...etc...
	// Pulse?
	if (iLevel > 3)
		y = BOTS_HUD_drawSwitch(y - BOTS_HUD_PANEL_MARGIN,iTeam,&stPulse,cgs.media.botsHUDiconsOther[bodyguard_pulse]); // Pack it

	
	// Protection...
	y = BOTS_HUD_drawSwitch(y,iTeam,&stProtect,cgs.media.botsHUDiconsOther[bodyguard_protection]);
	if (stProtected.iData != -1) {
		y = BOTS_HUD_drawClassInfo(y,stProtected.iData,-1);
	}


	return y;
}

static float BOTS_HUD_panelSNIPER(float y, int iLevel, int iTeam) {
	static stData_t		
		stCloak, stSight, stCloakwalk;
	bots_g2cg_sniper_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_sniper_t);


	updateData(&stSight,		(p->bits & (1<<BOTS_G2CG_SNIPER_SIGHT))?1:0);
	updateData(&stCloakwalk,	(p->bits & (1<<BOTS_G2CG_SNIPER_CLOAKWALK))?1:0);


	if (p->bits & (1<<BOTS_G2CG_SNIPER_CLOAKED)) {
		// Cloaked
		y = BOTS_HUD_drawIcon(y,iTeam,cgs.media.botsHUDiconsOther[sniper_visibility],cgs.media.botsHUDiconsOther[reserved0],qfalse,qfalse);
	}
	else {
		int num = p->sCloakTime;

		if (num>9) num=9;
		updateData(&stCloak,num);
		switch (stCloak.iData) {
		case -1:
			// Moving
			y = BOTS_HUD_drawIcon(y,iTeam,cgs.media.botsHUDiconsOther[sniper_visibility],cgs.media.botsHUDiconsOther[reserved1],qfalse,qfalse);
			break;
		case 0:
			// Cloaking
			y = BOTS_HUD_drawIcon(y,iTeam,cgs.media.botsHUDiconsOther[sniper_visibility],cgs.media.botsHUDiconsOther[reserved0],qfalse,qtrue);
			break;
		default:
			// Timer
			y = BOTS_HUD_drawIcon(y,iTeam,cgs.media.botsHUDiconsOther[sniper_visibility],cgs.media.botsHUDiconsOther[number_0 + stCloak.iData],qtrue,qfalse);
			break;
		}
	}
	// Sight
	y = BOTS_HUD_drawSwitch(y-BOTS_HUD_PANEL_MARGIN,iTeam,&stSight,cgs.media.botsHUDiconsOther[sniper_sight]);

	// CloakWalk
	if (iLevel > 3)
		y = BOTS_HUD_drawSwitch(y,iTeam,&stCloakwalk,cgs.media.botsHUDiconsOther[sniper_cloakwalk]);

	return y+BOTS_HUD_PANEL_MARGIN;
}

static float BOTS_HUD_panelKAMIKAZEE(float y, int iLevel, int iTeam) {
	static stData_t
		stWeapon,stGrenade,stAutorewire,stLongrange,stStick;
	bots_g2cg_kamikazee_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_kamikazee_t);


	updateData(&stWeapon,		p->weapons.weaponmode);
	updateData(&stGrenade,		p->weapons.grenademode);

	updateData(&stAutorewire,	(p->bits & (1<<BOTS_G2CG_KAMIKAZEE_AUTOREWIRE))?1:0);
	updateData(&stLongrange,	(p->bits & (1<<BOTS_G2CG_KAMIKAZEE_LONGRANGE))?1:0);
	updateData(&stStick,		(p->bits & (1<<BOTS_G2CG_KAMIKAZEE_STICKMODE))?1:0);

	// Weapon mode
	switch (stWeapon.iData) {
	case 2:
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stWeapon,cgs.media.botsHUDiconsOther[kami_cluster]);
		break;
	case 1:
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stWeapon,cgs.media.botsHUDiconsOther[kami_detmode]);
		break;
	default:
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stWeapon,cgs.media.botsHUDiconsOther[generic_normal]);
		break;
	}
	// Nuke
	if (iLevel>2)
		y = BOTS_HUD_drawSwitch(y-BOTS_HUD_PANEL_MARGIN,iTeam,&stGrenade,cgs.media.botsHUDiconsOther[grenade_nuke]);

	// Sticky
	if (iLevel>1) 
		y = BOTS_HUD_drawSwitch(y,iTeam,&stStick,cgs.media.botsHUDiconsOther[kami_sticky]);

	// Longrange
	if (iLevel>2) 
		// Pack it a bit
		y = BOTS_HUD_drawSwitch(y-BOTS_HUD_PANEL_MARGIN,iTeam,&stLongrange,cgs.media.botsHUDiconsOther[kami_longrange]);

	// Autorewire
	y = BOTS_HUD_drawSwitch(y,iTeam,&stAutorewire,cgs.media.botsHUDiconsOther[kami_autorewire]);

	return y;
}

static float BOTS_HUD_panelSOLDIER(float y, int iLevel, int iTeam) {
	static stData_t
		stWeapon, stTag, stGuided, stConquer;
	bots_g2cg_soldier_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_soldier_t);

	if (p->bits & (1<<BOTS_G2CG_SOLDIER_TAG))
		updateData(&stWeapon,	-2);
	else if (p->bits & (1<<BOTS_G2CG_SOLDIER_GUIDE))
		updateData(&stWeapon,	-1);
	else
		updateData(&stWeapon,	p->weapons.weaponmode);


	if (p->bits & (1<<BOTS_G2CG_SOLDIER_CONQUERED))
		updateData(&stConquer,	2);
	else
		updateData(&stConquer,	(p->bits & (1<<BOTS_G2CG_SOLDIER_CONQUERMODE))?1:0);


	// Weapon mode... Lots of possible modes ;)
	switch (stWeapon.iData) {
	case -2:
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stWeapon,cgs.media.botsHUDiconsOther[soldier_tag]);	
		break;
	case -1:
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stWeapon,cgs.media.botsHUDiconsOther[soldier_guided]);
		break;
	case 0:
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stWeapon,cgs.media.botsHUDiconsOther[generic_normal]);
		break;
	default:
		y = BOTS_HUD_drawWeaponMode(y,iTeam,&stWeapon,cgs.media.botsHUDiconsOther[generic_split + stWeapon.iData]);
		break;
	}

	// Conquer
	if (iLevel > 0) {
		switch (stConquer.iData) {
			// OFF
		case 0:
			y = BOTS_HUD_drawIcon(y,iTeam,cgs.media.botsHUDiconsOther[soldier_conquer],cgs.media.botsHUDiconsTeam[0][iTeam-1],qfalse,qfalse);
			break;
			// ON
		case 1:
			y = BOTS_HUD_drawIcon(y,iTeam,cgs.media.botsHUDiconsOther[soldier_conquer],cgs.media.botsHUDiconsTeam[1][iTeam-1],qfalse,qfalse);
			break;
			// Conquered
		case 2:
			y = BOTS_HUD_drawIcon(y,iTeam,cgs.media.botsHUDiconsOther[soldier_conquer],cg_items[ ITEM_INDEX(BG_FindItemForPowerup( iTeam == TEAM_RED ? PW_BLUEFLAG : PW_REDFLAG )) ].icon,qfalse,qtrue);
			break;
		}
	}
	return y;
}

static float BOTS_HUD_panelBERZERKER(float y, int iLevel, int iTeam) {
	static stData_t
		stQuad, stCharge, stParasites;
	bots_g2cg_berzerker_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_berzerker_t);


	updateData(&stQuad,			p->sQuadTime);
	updateData(&stCharge,		p->sChargeTime>0?p->sChargeTime:0);
	updateData(&stParasites,	p->sParasites);


	y = BOTS_HUD_drawTimer(y,iTeam,&stQuad,cgs.media.botsHUDiconsOther[berzerker_autoquad]);
	y = BOTS_HUD_drawTimer(y,iTeam,&stCharge,cgs.media.botsHUDiconsOther[berzerker_autocharge]);
	y = BOTS_HUD_drawTimer(y,iTeam,&stParasites,cgs.media.botsHUDiconsOther[berzerker_parasites]);

	return y;
}

static float BOTS_HUD_panelINFILTRATOR(float y, int iLevel, int iTeam) {
	static stData_t
		stSteal, stDisguiseClass, stDisguise, stGrenademode;
	bots_g2cg_infiltrator_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_infiltrator_t);
	
	updateData(&stDisguise,			p->sDisguiseTime);
	updateData(&stDisguiseClass,	p->sDisguiseClass);
	updateData(&stSteal,			(p->bits & (1<<BOTS_G2CG_INFILTRATOR_STEAL))?1:0);

	// Grenade mode
	updateData(&stGrenademode,	p->weapons.grenademode);
	y = BOTS_HUD_drawSwitch(y,iTeam,&stGrenademode,cgs.media.botsHUDiconsOther[grenade_decoy]);

	// Steal
	y = BOTS_HUD_drawSwitch(y,iTeam,&stSteal,cgs.media.botsHUDiconsOther[infiltrator_steal]);

	// Disguise?
	if (stDisguise.iData != -2) {
		if (stDisguise.iData == -1)
			stDisguise.iData = 99999;	// Team disguise => Infinite time

		y = BOTS_HUD_drawTimer(y,iTeam,&stDisguise,cgs.media.botsHUDiconsOther[infiltrator_disguise]);

		// Integrity checking
		if ((stDisguiseClass.iData < 1) || (stDisguiseClass.iData > 9))
			return y+BOTS_HUD_PANEL_MARGIN;

		y = BOTS_HUD_drawClassInfo(y,cg.snap->ps.clientNum,stDisguiseClass.iData);
	}
	return y;
}

static float BOTS_HUD_panelNURSE(float y, int iLevel, int iTeam) {
	static stData_t
		stPoison,stGrenademode;
	bots_g2cg_nurse_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_nurse_t);

	updateData(&stPoison,			(p->bits & (1<<BOTS_G2CG_NURSE_POISON))?1:0);
	updateData(&stGrenademode,		p->weapons.grenademode);

	// Grenade mode
	y = BOTS_HUD_drawSwitch(y,iTeam,&stGrenademode,cgs.media.botsHUDiconsOther[grenade_flash]);

	// Poison
	y = BOTS_HUD_drawSwitch(y,iTeam,&stPoison,cgs.media.botsHUDiconsOther[nurse_poison]);
	return y;
}

static float BOTS_HUD_panelSCIENTIST(float y, int iLevel, int iTeam) {
	static stData_t
		stKey,stGrenademode;
	bots_g2cg_scientist_t	
		*p = BOTS_G2CG_GETCLASSDATA(bots_g2cg_scientist_t);

	updateData(&stKey,				p->sKeyDistance);
	updateData(&stGrenademode,		p->weapons.grenademode);

	// Grenade mode
	y = BOTS_HUD_drawSwitch(y,iTeam,&stGrenademode,cgs.media.botsHUDiconsOther[grenade_tele]);
	// Key...
	y = BOTS_HUD_drawKey(y,iTeam,&stKey,cgs.media.botsHUDiconsOther[generic_key]);
	return y;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The master caller for classes
float BOTS_newDrawClassData(float y, int iClass, int iLevel, int iTeam) {


	// Don't display if dead or if the user is asking for a clean screen
	if ((cg_drawStatus.integer == 0) || (cg.snap->ps.stats[STAT_HEALTH] <= 0)) {
		return y;
	}


	if ((iClass<1) || (iClass>9)) {
		// CG_Printf("BOTS_DrawClassDataTEST: invalid class %i\n",iClass); 
		return y;
	}
	if ((iLevel<0) || (iLevel>4)) {
		// CG_Printf("BOTS_DrawClassDataTEST: invalid level %i\n",iLevel); 
		return y;
	}
	if ((iTeam<TEAM_RED) || (iTeam>TEAM_BLUE)) {
		// CG_Printf("BOTS_DrawClassDataTEST: invalid team %i\n",iTeam); 
		return y;
	}

	if (cg_HUDstyle.integer & BOTS_HUD_CLASSICON) {
		y = BOTS_HUD_drawClassIcon(y,BOTS_HUD_PANEL_WIDTH,iClass,iLevel,iTeam);
	}
	else
		y = BOTS_HUD_drawClassText(y,iClass,iLevel,iTeam);

	// CG_Printf("\nclass %i ",iClass);
	switch (iClass) {
	case BOTS_CAPTAIN:
		y = BOTS_HUD_panelCAPTAIN(y,iLevel,iTeam);
		break;
	case BOTS_BODYGUARD:
		y = BOTS_HUD_panelBODYGUARD(y,iLevel,iTeam);
		break;
	case BOTS_SNIPER:
		y = BOTS_HUD_panelSNIPER(y,iLevel,iTeam);
		break;
	case BOTS_SOLDIER:
		y = BOTS_HUD_panelSOLDIER(y,iLevel,iTeam);
		break;
	case BOTS_BERZERKER:
		y = BOTS_HUD_panelBERZERKER(y,iLevel,iTeam);
		break;
	case BOTS_INFILTRATOR:
		y = BOTS_HUD_panelINFILTRATOR(y,iLevel,iTeam);
		break;
	case BOTS_KAMIKAZEE:
		y = BOTS_HUD_panelKAMIKAZEE(y,iLevel,iTeam);
		break;
	case BOTS_NURSE:
		y = BOTS_HUD_panelNURSE(y,iLevel,iTeam);
		break;
	case BOTS_SCIENTIST:
		y = BOTS_HUD_panelSCIENTIST(y,iLevel,iTeam);
		break;
	}
	return y;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


static int BOTS_getWeapon2Ammo(weapon_t weapon) {
	switch(weapon) {
	case WP_STINGER:
		return AMMO_BFG;
	case WP_PLASMAGUN:
		return AMMO_BFG;
	case WP_LIGHTNING:
		return AMMO_BFG;
	case WP_GRAPPLING_HOOK:
		return AMMO_BFG;
	case WP_BFG:
		return AMMO_BFG;

	case WP_SHOTGUN:
		return AMMO_SHELLS;
	case WP_RAILGUN:
		return AMMO_SLUGS;
	case WP_ROCKET_LAUNCHER:
		return AMMO_ROCKETS;
	case WP_GRENADE_LAUNCHER:
		return AMMO_GRENADES;
	case WP_MACHINEGUN:
		return AMMO_BULLETS;
	case WP_GAUNTLET:
	default:
		return -1;
	}
}

static weapon_t BOTS_getAmmo2Weapon(int iAmmo) {
	switch (iAmmo)
	{
	case AMMO_SHELLS:
		return WP_SHOTGUN;
	case AMMO_BULLETS:
		return WP_MACHINEGUN;
	case AMMO_ROCKETS:
		return WP_ROCKET_LAUNCHER;
	case AMMO_SLUGS:
		return WP_RAILGUN;

	case AMMO_GRENADES:
		return WP_GRENADE_LAUNCHER;
	//case WP_STINGER:
	//case WP_PLASMAGUN:
	//case WP_LIGHTNING:
	//case WP_BFG:
	case AMMO_BFG:
		return WP_BFG;
	default:
		return WP_NONE;
	}
}

static float BOTS_newDraw_Ammo(int y, int iAmmo)
{
	const int
		w	= (BOTS_HUD_FIELD_WIDTH*3) + BOTS_HUD_FIELD_HEIGHT + BOTS_HUD_FIELD_MARGIN,
		y1	= y + BOTS_HUD_FIELD_MARGIN/2,
		w1	= BOTS_HUD_FIELD_HEIGHT-BOTS_HUD_FIELD_MARGIN,
		h1	= BOTS_HUD_FIELD_HEIGHT-BOTS_HUD_FIELD_MARGIN;
	qhandle_t	icon;
	int			x,l;



	x = 640 - w;

	// Draw the ammo #
	l = cg.snap->ps.ammo[BOTS_getAmmo2Weapon(iAmmo)];
	// Try to guess if we're drawing the ammo being used by the current weapon
	// If so, clue the player
	if ((cg.weaponSelect != WP_STINGER) && (BOTS_getWeapon2Ammo(cg.weaponSelect) == iAmmo)) {
		static vec4_t colors[2] = {
			{ 0,0,0,1 },	// Black
			{ 1,1,0,1 }		// Yellow
		};
		int x1 = x;

		if (l > 99)	// If the number was big, move it a bit
			x1 -= BOTS_HUD_FIELD_WIDTH;

		trap_R_SetColor(colors[0]);
		CG_DrawChar(x1+2, y1+2, w1, h1, 'z'+19 );
		trap_R_SetColor(colors[1]);
		CG_DrawChar(x1, y1, w1, h1, 'z'+19 );
		trap_R_SetColor(NULL);
	}

	trap_R_SetColor( colors[0] );
	BOTS_DrawField (x, y, 3, l);	
	trap_R_SetColor( NULL );

	
	// Ammo icon
	x += (BOTS_HUD_FIELD_WIDTH*3);
	icon = cg_items[iAmmo].icon;
	if (icon) {
		x += BOTS_HUD_FIELD_MARGIN;
		// Offset/Shrink it a bit
		CG_DrawPic(x + BOTS_HUD_FIELD_MARGIN/2, y1, w1, h1, icon );
		x += BOTS_HUD_FIELD_HEIGHT;
	}
	y += BOTS_HUD_FIELD_HEIGHT+BOTS_HUD_FIELD_MARGIN;
	return y;
}

static int BOTS_DrawProxy(int x, int y, int w, int h, int iNumber) {
	vec4_t	colors[] = {
		{ 0,0,0,1 },	// Black
		{ 0,1,0,1 }		// Green
	};
	const int nudge = 6;

	if (iNumber == -1)
		return x;

	if (iNumber > 9)
		iNumber = 9;
	else if (iNumber < 0)
		iNumber = 0;

	x -= w;

	trap_R_SetColor(colors[0]);
	CG_DrawPic( x+2+(nudge/2), y+2+(nudge/2), w-nudge, h-nudge, cgs.media.numberShaders[iNumber] );
	trap_R_SetColor(colors[1]);
	CG_DrawPic( x+(nudge/2), y+(nudge/2), w-nudge, h-nudge, cgs.media.numberShaders[iNumber] );

	// Box around
	CG_DrawPic( x, y, w, h, cgs.media.selectShader );
	trap_R_SetColor(NULL);

	return x;
}

static float BOTS_panelAmmo(float y) {
	static int 
		ammoList[10][5] = { // Weapon, nb ammo, then ammo: main weapon firts, grenades last
		{ WP_STINGER,2,				AMMO_BFG, AMMO_GRENADES },				// Default
		{ WP_BFG, 2,				AMMO_BFG, AMMO_GRENADES },				// BOTS_CAPTAIN
		{ WP_SHOTGUN, 3,			AMMO_SHELLS, AMMO_BFG, AMMO_GRENADES },	// BOTS_BODYGUARD
		{ WP_RAILGUN, 3,			AMMO_SLUGS, AMMO_BFG, AMMO_GRENADES },	// BOTS_SNIPER
		{ WP_ROCKET_LAUNCHER,2,		AMMO_ROCKETS, AMMO_GRENADES },			// BOTS_SOLDIER
		{ WP_GAUNTLET, 1,			AMMO_GRENADES },						// BOTS_BERZERKER
		{ WP_PLASMAGUN, 2,			AMMO_BFG, AMMO_GRENADES },				// BOTS_INFILTRATOR
		{ WP_GRENADE_LAUNCHER,2,	AMMO_BFG, AMMO_GRENADES },				// BOTS_KAMIKAZEE
		{ WP_MACHINEGUN,3,			AMMO_BULLETS, AMMO_BFG, AMMO_GRENADES },// BOTS_NURSE
		{ WP_LIGHTNING,2,			AMMO_BFG, AMMO_GRENADES }				// BOTS_SCIENTIST
	};
	const int 
		h = BOTS_HUD_FIELD_HEIGHT+BOTS_HUD_FIELD_MARGIN,
		w =  (BOTS_HUD_FIELD_WIDTH*3) + BOTS_HUD_FIELD_HEIGHT + BOTS_HUD_FIELD_MARGIN,
		x = 640 - w;
	int	
		*p,
		nbslots,
		i,
		numGrens1, numGrens2;



	// No ammo if dead
	if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
		return y;
	}
	
	if ((iCLASSTYPE<1) || (iCLASSTYPE>9)) // Bogus?
		iCLASSTYPE = 0;

	p = (int *) (ammoList+iCLASSTYPE); // Fuck that low priority casting operator!


	// Draw from bottom->top
	y -= BOTS_HUD_FIELD_MARGIN;
	nbslots = p[BOTS_PANEL_AMMO_SLOTS];

	// Proxies? Decoys?
	switch (iCLASSTYPE) {
	case BOTS_CAPTAIN:
		numGrens1 = BOTS_G2CG_GETCLASSDATA(bots_g2cg_captain_t)->weapons.gren1;
		numGrens2 = -1;
		nbslots++;
		break;

	case BOTS_BODYGUARD:
		numGrens1 = BOTS_G2CG_GETCLASSDATA(bots_g2cg_bodyguard_t)->weapons.gren1;
		numGrens2 = -1;
		nbslots++;
		break;

	case BOTS_INFILTRATOR:
		numGrens1 = BOTS_G2CG_GETCLASSDATA(bots_g2cg_infiltrator_t)->weapons.gren1;
		numGrens2 = -1;
		nbslots++;
		break;

	case BOTS_KAMIKAZEE:
		numGrens1 = BOTS_G2CG_GETCLASSDATA(bots_g2cg_kamikazee_t)->weapons.gren1;
		numGrens2 = BOTS_G2CG_GETCLASSDATA(bots_g2cg_kamikazee_t)->weapons.gren2;
		nbslots++;
		break;

	default:
		numGrens1 = -1;
		numGrens2 = -1;
		break;
	}

	CG_DrawTeamBackground( x, y - (nbslots*h) - BOTS_HUD_FIELD_MARGIN, w, BOTS_HUD_FIELD_MARGIN + (nbslots*h), 0.33, cg.snap->ps.persistant[PERS_TEAM] );
	for (i=0;i<p[BOTS_PANEL_AMMO_SLOTS]; i++) {
		y -= h;
		BOTS_newDraw_Ammo(y,p[BOTS_PANEL_AMMO_AMMO + i]);
	}

	// Now, draw the proxy/decoy/detpipe indicator
	if ((numGrens1 != -1) || (numGrens2 != -1)) {
		y -= h;
		BOTS_DrawProxy(BOTS_DrawProxy(640,y,BOTS_HUD_FIELD_HEIGHT,BOTS_HUD_FIELD_HEIGHT,numGrens2),
			y,BOTS_HUD_FIELD_HEIGHT,BOTS_HUD_FIELD_HEIGHT,numGrens1); // Haha, readable code? Where?
	}
	y -= BOTS_HUD_FIELD_MARGIN;
	return y;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// see CG_ParseAnimationFile()
void BOTS_drawUgly() {
#if 0
	const int
		iDuration	= 25000,
		iMaxUgly	= 5,
		iMaxAdvice	= 1,
		iUglySize	= 128,
		iFrameWidth = 256;
	static int 
		iTime = 0,
		iUglyIndex	= 0,
		iUglyAdvice	= 0,
		seed = 0x92;
	static qhandle_t UglyHandle = 0;

	int
		x, y;
	vec4_t hcolor;


	if (iTime == 0) {
		iTime = cg.time;
		iUglyIndex = ((cg.time+rand())/100)%iMaxUgly;
		iUglyAdvice = ((cg.time+rand())/100)%iMaxAdvice;
	}
	else {
		if ((cg.time - iTime)>iDuration)
			return;
	}

	if (UglyHandle == -1)
		return;

	if (UglyHandle == 0) {
		char sBuf[256];
		
		Com_sprintf(sBuf,256,"bots/hud/ugly/ugly%i.tga",iUglyIndex);
		CG_Printf("Loading Ugly #%i\n",iUglyIndex);
		UglyHandle = trap_R_RegisterShaderNoMip(sBuf);
		if (UglyHandle == 0) {
			// Mark it as bad
			UglyHandle = -1;
			CG_Printf("Bad!\n");
			return;
		}
	}

	y = (480 - iUglySize)/2;
	x = (640 - (iUglySize+iFrameWidth))/2;

	CG_DrawPic( x, y, iUglySize, iUglySize, UglyHandle );
	x += iUglySize;

	hcolor[0] = 0.6;	hcolor[1] = 0.6; hcolor[2] = 0.6; hcolor[3] = 0.33;
	trap_R_SetColor( hcolor );
	CG_DrawPic( x, y, iFrameWidth, iUglySize, cgs.media.teamStatusBar );
	trap_R_SetColor( NULL );
#endif
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static float BOTS_DrawPromoTechPoints(float y) {
	int			x, w, y1;
	int			iTeam;
	vec4_t		color;
	const char	*s;
	bots_game2cgame_t	
		*p = BOTS_G2CG_GETDATA();
	static stData_t
		stPromopts,stTechpts;

	
	if ( cgs.gametype < GT_TEAM )
		return y; // Hmmppfff

	switch (cgs.clientinfo[cg.snap->ps.clientNum].team) {
	case TEAM_RED:
		iTeam = 0;
		color[0] = 1; color[1] = 0; color[2] = 0; color[3] = 0.33;
		break;
		
	case TEAM_BLUE:
		iTeam = 1;
		color[0] = 0; color[1] = 0; color[2] = 1; color[3] = 0.33;
		break;
		
	default:
		return y;
	}


	// Update those damn numbers
	updateData(&stPromopts,	p->ucPromoPoints);
	updateData(&stTechpts,	p->ucTechPoints);
	


	if (cg_HUDstyle.integer & BOTS_HUD_NEWHUD) {
		s = va( "%2i", stTechpts.iData);
		w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH + 8;
		s = va( "%2i", stPromopts.iData );
		w += CG_DrawStrlen( s ) * BIGCHAR_WIDTH + 8;
		
		// draw from the right side to left, need to precalc
		// in the bottom left corner
		y = 480 - ( BIGCHAR_HEIGHT + 8 );
		y1 = y;		
		x = w;
	}
	else {
		y -=  BIGCHAR_HEIGHT + 8;
		y1 = y;
		
		// draw from the right side to left
		x = 640;
	}

	// Tech points
	s = va( "%2i", stTechpts.iData);
	w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH + 8;
	x -= w;
	CG_FillRect( x, y-4,  w, BIGCHAR_HEIGHT+8, color );
	CG_DrawBigString( x + 4, y, s, 1.0F);	
	y1 = y - BIGCHAR_HEIGHT - 8;
	CG_DrawPic( x, y1-4, w, BIGCHAR_HEIGHT+8, cgs.media.botsHUDiconsTeam[3][iTeam] );

	// Promo points
	s = va( "%2i", stPromopts.iData );
	w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH + 8;
	x -= w;
	CG_FillRect( x, y-4,  w, BIGCHAR_HEIGHT+8, color );
	CG_DrawBigString( x + 4, y, s, 1.0F);
	y1 = y - BIGCHAR_HEIGHT - 8;
	CG_DrawPic( x, y1-4, w, BIGCHAR_HEIGHT+8, cgs.media.botsHUDiconsTeam[2][iTeam] );

	return y1 - 8;
}

void BOTS_newDrawStatusBar() 
{
	playerState_t	*ps;
	vec4_t			hcolor;
	vec3_t		
		angles,
		origin;
	int
		value,
		x,
		y;
	qboolean	bDecoy = qfalse;

	
	if ((cg_drawStatus.integer == 0)||!(cg_HUDstyle.integer & BOTS_HUD_NEWHUD)) {
		return;
	}
	
	// ???
	// BOTS_Draw_Current_Weapon();

	BOTS_DrawPickupItem( 420);

	// draw the team background
	CG_DrawTeamBackground( 0, 420, 640, 60, 0.33, cg.snap->ps.persistant[PERS_TEAM] );
	
	ps = &cg.snap->ps;
	VectorClear( angles );

	x = 90 + 20;
	y = 432 - TEXT_ICON_SPACE;	

	// Flag
	// don't display flag in decoymode
	if (iCLASSTYPE == BOTS_BODYGUARD) {
		int decoymode = atoi(Info_ValueForKey(info, "d"));

		if (decoymode > cg.time)
			bDecoy = qtrue;
	}

	if (!bDecoy) {
		if (cg.predictedPlayerState.powerups[PW_REDFLAG])
			BOTS_DrawStatusBarFlag( x, y, TEAM_RED);
		else if (cg.predictedPlayerState.powerups[PW_BLUEFLAG])
			BOTS_DrawStatusBarFlag( x, y, TEAM_BLUE);
	}


	x = 185;
	// Health
	value = ps->stats[STAT_HEALTH];
	CG_ColorForHealth( hcolor );
	BOTS_DrawFieldBig( x, y, 3, value, hcolor );
	BOTS_DrawStatusBarHead( x + BOTS_HUD_FIELD_BIG_WIDTH*3 + TEXT_ICON_SPACE );	
	
	
	x = 370;
	// y = 432;
	// Armor
	value = ps->stats[STAT_ARMOR];
	if (value > 0 ) {
		BOTS_DrawFieldBig (x, y, 3, value, colors[0]);

		// if we didn't draw a 3D icon, draw a 2D icon for armor
		if ( !cg_draw3dIcons.integer && cg_drawIcons.integer ) {
			CG_DrawPic( x + BOTS_HUD_FIELD_BIG_WIDTH*3 + TEXT_ICON_SPACE, y, BOTS_HUD_BIG_ICONSIZE, BOTS_HUD_BIG_ICONSIZE, cgs.media.armorIcon );
		}
		else {
			origin[0] = 90;
			origin[1] = 0;
			origin[2] = -10;
			angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
			CG_Draw3DModel( x + BOTS_HUD_FIELD_BIG_WIDTH*3 + TEXT_ICON_SPACE, 432, BOTS_HUD_BIG_ICONSIZE, BOTS_HUD_BIG_ICONSIZE,
				cgs.media.armorModel, 0, origin, angles );
		}
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Master callers

void BOTS_DrawUpperRight()
{
	float	y;

// BEGIN bots - tbp
	y = 0;

	// In follow mode, draw the name of the player followed first
	// see CG_DrawFollow()
	if (cg.snap->ps.pm_flags & PMF_FOLLOW) {
		float		x;
		vec4_t		color;
		const char	*name;

		color[0] = 1; color[1] = 1; color[2] = 1; color[3] = 1;
		name = cgs.clientinfo[ cg.snap->ps.clientNum ].name;
		// x = 0.5 * ( 640 - SMALLCHAR_WIDTH * CG_DrawStrlen( name ) );
		x = 635 - (BIGCHAR_WIDTH * CG_DrawStrlen( name ));
		CG_DrawStringExt( x, y, name, color, qfalse, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 );
		y += BIGCHAR_HEIGHT + 4;
	}

// END bots - tbp
	// disabled team overlay - too much of a bandwidth hog.
	//if ( cgs.gametype >= GT_TEAM && cg_drawTeamOverlay.integer == 1 )
	//	y = CG_DrawTeamOverlay( y, qtrue, qtrue );

	if ( cg_drawSnapshot.integer )
		y = CG_DrawSnapshot( y );
	
	if ( cg_drawFPS.integer )
		y = CG_DrawFPS( y );
	
	if ( cg_drawTimer.integer )
		y = CG_DrawTimer( y );

	
	y = BOTS_newDrawClassData(y,iCLASSTYPE,iLEVEL,cgs.clientinfo[cg.snap->ps.clientNum].team);
}

void BOTS_DrawLowerRight( qboolean bSpectator) {
	float	y;


	// Start at the very bottom
	y = 480;


	y = CG_DrawScores( y );

	if (!bSpectator) {
		y = BOTS_DrawPromoTechPoints(y);

		if (cg_drawTeamOverlay.integer != 0) 
			CG_DrawTeamOverlay( y-BOTS_HUD_PANEL_MARGIN, qtrue, qfalse );
		
		y = BOTS_panelAmmo(y);
	}

	y = CG_DrawLagometer( y );

	if (!bSpectator)
		y = CG_DrawPowerups( y );
}
